package morenoapp;

import java.awt.Color;
import morenoapp.util.Order;
import morenoapp.action.MorenoActionsFacade;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import javax.swing.AbstractButton;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JRootPane;
import javax.swing.JSeparator;
import javax.swing.JTextField;
import javax.swing.JToggleButton;
import javax.swing.JToolBar;
import javax.swing.LookAndFeel;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
import morenoapp.action.resources.ActionsResourcesHolder;
import morenoapp.components.common.LinkLabel;
import morenoapp.components.workplace.Workplace;
import morenoapp.components.workplace.WorkplaceNavigator;
import morenoapp.model.listeners.MorenoModelAdapter;
import morenoapp.model.listeners.MorenoModelListener;
import morenoapp.resources.ResourcesHolder;
import morenoapp.util.I18N;
import morenoapp.util.MorenoUtil;
import morenoapp.util.ShouldNotHappenException;
import org.jdesktop.application.FrameView;
import org.jdesktop.application.SingleFrameApplication;

/**
 *
 * @author dmitry.mamonov
 */
public class MorenoMainView extends FrameView {
    //model
    @Order(value = 0)
    private MorenoApp application;
    @Order(value = 0)
    private Workplace workplace = new Workplace();
    //components: menu->research
    @Order(value = 10)
    private JMenu menuResearch;
    @Order(value = 20)
    private JMenuItem menuItemStartNewResearch;
    @Order(value = 30)
    private JMenuItem menuItemImportResearch;
    @Order(value = 40)
    private JMenuItem menuItemOpenResearch;
    @Order(value = 50)
    private JMenuItem menuItemSaveResearch;
    @Order(value = 60)
    private JMenuItem menuItemSaveResearchAs;
    @Order(value = 70)
    private JMenuItem menuItemCloseResearch;
    @Order(value = 71)
    private JMenuItem menuItemExitApp;
    //components: menu->options
    @Order(value = 73)
    private JMenu menuNavigate;
    @Order(value = 74)
    private JMenuItem menuItemWizardView;
    @Order(value = 75)
    private JMenuItem menuItemTabbedView;
    @Order(value = 76)
    private JMenuItem menuItemNavigatePrev;
    @Order(value = 77)
    private JMenuItem menuItemNavigateNext;
    //components: menu->options
    @Order(value = 80)
    private JMenu menuOptions;
    @Order(value = 90)
    private JMenuItem menuItemRussian;
    @Order(value = 100)
    private JMenuItem menuItemEnglish;
    @Order(value = 110)
    private JMenuItem menuItemNoInternet;
    //components: menu->tools (only for debug mode)
    @Order(value = 120)
    private JMenu menuTools;
    @Order(value = 130)
    private JMenuItem menuItemTakeAllScreens;
    @Order(value = 140)
    private JMenuItem menuItemTakeMainScreens;
    @Order(value = 150)
    private JMenuItem menuItemTakeFormsScreens;
    //components: menu->help
    @Order(value = 160)
    private JMenu menuHelp;
    @Order(value = 170)
    private JMenuItem menuItemSubmitIssue;
    @Order(value = 180)
    private JMenuItem menuItemAboutProgram;
    @Order(value = 190)
    private JMenuItem menuItemShowApplicationHelp;
    //components: toolbar
    @Order(value = 200)
    private JButton buttonStartNewResearch;
    @Order(value = 210)
    private JButton buttonImportResearch;
    @Order(value = 220)
    private JButton buttonOpenResearch;
    @Order(value = 230)
    private JButton buttonSaveResearch;
    @Order(value = 240)
    private JButton buttonSaveResearchAs;
    @Order(value = 250)
    private JToggleButton toggleWizardMode;
    @Order(value = 260)
    private JButton buttonNavigateNext;
    @Order(value = 270)
    private JButton buttonNavigatePrev;
    @Order(value = 280)
    private JButton buttonShowApplicationHelp;
    @Order(value = 290)
    private JButton buttonCloseReserch;
    //components: statusbar
    @Order(value = 300)
    private JLabel labelStatus;
    @Order(value = 310)
    private JButton buttonException;
    public MorenoMainView(SingleFrameApplication app) {
        super(app);
        application = (MorenoApp) app;

        initMenu();
        initToolbar();
        initStatusbar();
        initLayout();
        initListeners();
        initState();
    }

    private void initMenu() {
        JMenuBar menuBar = new JMenuBar();
        setMenuBar(menuBar);
        { //menuResearch
            JMenu menu = new JMenu();
            menu.setName("menuResearch");
            menu.setText(I18N.get("menu.research"));
            { //menuItemStartNewResearch
                JMenuItem item = new JMenuItem();
                item.setName("menuItemStartNewResearch");
                item.setAction(MorenoActionsFacade.getActionCreateNewModel());
                menu.add(item);
                menuItemStartNewResearch = item;
            }
            { //menuItemImportResearch
                JMenuItem item = new JMenuItem();
                item.setName("menuItemImportResearch");
                item.setAction(MorenoActionsFacade.getActionImportResearch());
                menu.add(item);
                menuItemImportResearch = item;
            }
            { //menuItemOpenResearch
                JMenuItem item = new JMenuItem();
                item.setName("menuItemOpenResearch");
                item.setAction(MorenoActionsFacade.getActionOpenModel());
                menu.add(item);
                menuItemOpenResearch = item;
            }
            { //menuItemSaveResearch
                JMenuItem item = new JMenuItem();
                item.setName("menuItemSaveResearch");
                item.setAction(MorenoActionsFacade.getActionSaveModel());
                menu.add(item);
                menuItemSaveResearch = item;
            }
            { //menuItemSaveResearchAs
                JMenuItem item = new JMenuItem();
                item.setName("menuItemSaveResearchAs");
                item.setAction(MorenoActionsFacade.getActionSaveAsModel());
                menu.add(item);
                menuItemSaveResearchAs = item;
            }
            { //menuItemCloseResearch
                JMenuItem item = new JMenuItem();
                item.setName("menuItemCloseResearch");
                item.setAction(MorenoActionsFacade.getActionCloseModel());
                menu.add(item);
                menuItemCloseResearch = item;
            }
            menu.addSeparator();
            { //menuItemExitApp
                JMenuItem item = new JMenuItem();
                item.setName("menuItemExitApp");
                item.setAction(MorenoActionsFacade.getActionExitApp());
                menu.add(item);
                menuItemExitApp = item;
            }
            getMenuBar().add(menu);
            menuResearch = menu;
        }

        { //menuNavigate
            JMenu menu = new JMenu();
            menu.setName("menuNavigate");
            menu.setText(I18N.get("menu.navigation"));
            { //menuItemWizardView
                JMenuItem item = new JMenuItem();
                item.setName("menuItemWizardView");
                item.setAction(MorenoActionsFacade.getActionSwitchToWizardView());
                menu.add(item);
                menuItemWizardView = item;
            }
            { //menuItemTabbedView
                JMenuItem item = new JMenuItem();
                item.setName("menuItemTabbedView");
                item.setAction(MorenoActionsFacade.getActionSwitchToTabbedView());
                menu.add(item);
                menuItemTabbedView = item;
            }
            menu.addSeparator();
            { //menuItemNavigatePrev
                JMenuItem item = new JMenuItem();
                item.setName("menuItemNavigatePrev");
                item.setAction(MorenoActionsFacade.getActionNavigatePrev());
                menu.add(item);
                menuItemNavigatePrev = item;
            }
            { //menuItemNavigateNext
                JMenuItem item = new JMenuItem();
                item.setName("menuItemNavigateNext");
                item.setAction(MorenoActionsFacade.getActionNavigateNext());
                menu.add(item);
                menuItemNavigateNext = item;
            }
            getMenuBar().add(menu);
            menuNavigate = menu;
        }


        if (MorenoUtil.isDebug() == true) { //menuTools
            JMenu menu = new JMenu();
            menu.setName("menuTools");
            menu.setText(I18N.get("menu.tools"));
            { //setup look and feel options
                Map<String, String> lafsMap = new LinkedHashMap<String, String>();
                LookAndFeelInfo[] lafInfos = UIManager.getInstalledLookAndFeels();
                if (lafInfos != null) {
                    for (LookAndFeelInfo laf : lafInfos) {
                        lafsMap.put("LaF-Info: " + laf.getName(), laf.getClassName());
                    }
                }
                LookAndFeel lafs[] = UIManager.getAuxiliaryLookAndFeels();
                if (lafs != null) {
                    for (LookAndFeel laf : lafs) {
                        lafsMap.put("LaF: " + laf.getName(), laf.getClass().getName());
                    }
                }
                for (String laf : new String[]{
                            "com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel",
                            "com.jgoodies.looks.plastic.PlasticLookAndFeel",
                            "com.jgoodies.looks.plastic.Plastic3DLookAndFeel",
                            "com.jgoodies.looks.plastic.PlasticXPLookAndFeel",
                            "org.jvnet.substance.skin.SubstanceBusinessLookAndFeel",
                            "net.sourceforge.napkinlaf.NapkinLookAndFeel",}) {
                    lafsMap.put("LaF-Custom: " + laf, laf);
                }

                if (lafsMap.isEmpty() == false) {
                    for (Map.Entry<String, String> laf : lafsMap.entrySet()) {
                        final String lafName = laf.getKey();
                        final String lafClass = laf.getValue();
                        JMenuItem menuItem = new JMenuItem(lafName);
                        menuItem.setIcon(ActionsResourcesHolder.ICON_ACTION_TOOL_SMALL);
                        menuItem.addActionListener(new ActionListener() {
                            public void actionPerformed(ActionEvent e) {
                                try {
                                    UIManager.setLookAndFeel(lafClass);
                                    SwingUtilities.updateComponentTreeUI(MorenoApp.getApplication().getMainFrame());
                                } catch (UnsupportedLookAndFeelException ex) {
                                    throw new ShouldNotHappenException(ex);
                                } catch (ClassNotFoundException ex) {
                                    throw new ShouldNotHappenException(ex);
                                } catch (InstantiationException ex) {
                                    throw new ShouldNotHappenException(ex);
                                } catch (IllegalAccessException ex) {
                                    throw new ShouldNotHappenException(ex);
                                }
                            }

                        });
                        menu.add(menuItem);
                    }
                }
            }

            menu.addSeparator();
            { //menuItemTakeAllScreens
                JMenuItem item = new JMenuItem();
                item.setName("menuItemTakeAllScreens");
                item.setAction(MorenoActionsFacade.getActionDebugSavelAllComponentsAsImages());
                menu.add(item);
                menuItemTakeAllScreens = item;
            }
            { //menuItemTakeMainScreens
                JMenuItem item = new JMenuItem();
                item.setName("menuItemTakeMainScreens");
                item.setAction(MorenoActionsFacade.getActionDebugSaveImportantComponentsAsImages());
                menu.add(item);
                menuItemTakeMainScreens = item;
            }
            { //menuItemTakeFormsScreens
                JMenuItem item = new JMenuItem();
                item.setName("menuItemTakeFormsScreens");
                item.setAction(MorenoActionsFacade.getActionDebugMakeScreenshots());
                menu.add(item);
                menuItemTakeFormsScreens = item;
            }
            menu.addSeparator();
            { //reset install ID
                JMenuItem item = new JMenuItem();
                item.setName("menuItemResetInstallID");
                item.setAction(MorenoActionsFacade.getActionDebugResetInstallID());
                menu.add(item);
            }
            menu.addSeparator();
            { //throw exception
                JMenuItem item = new JMenuItem();
                item.setName("menuItemThrowException");
                item.setAction(MorenoActionsFacade.getActionThrowException());
                menu.add(item);
            }


            getMenuBar().add(menu);
            menuTools = menu;
        }
        { //menuOptions
            JMenu menu = new JMenu();
            menu.setName("menuOptions");
            menu.setText(I18N.get("menu.options"));
            { //menuItemRussian
                JMenuItem item = new JMenuItem();
                item.setName("menuItemRussian");
                item.setAction(MorenoActionsFacade.getActionSetUILanguageRussian());
                menu.add(item);
                menuItemRussian = item;
            }
            { //menuItemEnglish
                JMenuItem item = new JMenuItem();
                item.setName("menuItemEnglish");
                item.setAction(MorenoActionsFacade.getActionSetUILanguageEnglish());
                menu.add(item);
                menuItemEnglish = item;
            }
            { //menuItemNoInternet
                JMenuItem item = new JMenuItem();
                item.setName("menuItemNoInternet");
                item.setAction(MorenoActionsFacade.getActionToggleNetworkOption());
                menu.add(item);
                menuItemNoInternet = item;
            }
            getMenuBar().add(menu);
            menuOptions = menu;
        }
        { //menuHelp
            JMenu menu = new JMenu();
            menu.setName("menuHelp");
            menu.setText(I18N.get("menu.help"));
            { //menuItemSubmitIssue
                JMenuItem item = new JMenuItem();
                item.setName("menuItemSubmitIssue");
                item.setAction(MorenoActionsFacade.getActionSubmitIssue());
                menu.add(item);
                menuItemSubmitIssue = item;
            }
            { //menuItemAboutProgram
                JMenuItem item = new JMenuItem();
                item.setName("menuItemAboutProgram");
                item.setAction(MorenoActionsFacade.getActionAbout());
                menu.add(item);
                menuItemAboutProgram = item;
            }
            { //menuItemShowApplicationHelp
                JMenuItem item = new JMenuItem();
                item.setName("menuItemShowApplicationHelp");
                item.setAction(MorenoActionsFacade.getActionShowAppHelp());
                menu.add(item);
                menuItemShowApplicationHelp = item;
            }
            getMenuBar().add(menu);
            menuHelp = menu;
        }
    }

    private void initToolbar() {
        final Dimension separatorDimension = new Dimension(7, 32);
        setToolBar(new JToolBar());
        getToolBar().setLayout(new BoxLayout(getToolBar(), BoxLayout.LINE_AXIS));
        getToolBar().setFloatable(false);
        { //buttonStartNewResearch
            JButton button = new JButton();
            button.setName("buttonStartNewResearch");
            button.setAction(MorenoActionsFacade.getActionCreateNewModel());
            button.setText(null);
            button.setIcon(ActionsResourcesHolder.ICON_ACTION_NEW_MED);
            getToolBar().add(button);
            buttonStartNewResearch = button;
        }
        { //buttonImportResearch
            JButton button = new JButton();
            button.setName("buttonImportResearch");
            button.setAction(MorenoActionsFacade.getActionImportResearch());
            button.setText(null);
            button.setIcon(ActionsResourcesHolder.ICON_ACTION_IMPORT_MED);
            getToolBar().add(button);
            buttonImportResearch = button;
        }
        { //buttonOpenResearch
            JButton button = new JButton();
            button.setName("buttonOpenResearch");
            button.setAction(MorenoActionsFacade.getActionOpenModel());
            button.setText(null);
            button.setIcon(ActionsResourcesHolder.ICON_ACTION_OPEN_MED);
            getToolBar().add(button);
            buttonOpenResearch = button;
        }
        { //buttonSaveResearch
            JButton button = new JButton();
            button.setName("buttonSaveResearch");
            button.setAction(MorenoActionsFacade.getActionSaveModel());
            button.setText(null);
            button.setIcon(ActionsResourcesHolder.ICON_ACTION_SAVE_MED);
            getToolBar().add(button);
            buttonSaveResearch = button;
        }
        { //buttonSaveResearchAs
            JButton button = new JButton();
            button.setName("buttonSaveResearchAs");
            button.setAction(MorenoActionsFacade.getActionSaveAsModel());
            button.setText(null);
            button.setIcon(ActionsResourcesHolder.ICON_ACTION_SAVE_AS_MED);
            getToolBar().add(button);
            buttonSaveResearchAs = button;
        }
        getToolBar().addSeparator(separatorDimension);
        { //toggleWizardMode
            JToggleButton button = new JToggleButton();
            button.setName("toggleWizardMode");
            button.setAction(MorenoActionsFacade.getActionToggleWizardMode());
            button.setText(null);
            button.setIcon(ActionsResourcesHolder.ICON_ACTION_WIZARD_MED);
            getToolBar().add(button);
            toggleWizardMode = button;
        }
        { //buttonNavigatePrev
            JButton button = new JButton();
            button.setName("buttonNavigatePrev");
            button.setAction(MorenoActionsFacade.getActionNavigatePrev());
            button.setIcon(ActionsResourcesHolder.ICON_ACTION_NAVIGATE_PREV_MED);
            getToolBar().add(button);
            buttonNavigatePrev = button;
        }
        { //buttonNavigateNext
            JButton button = new JButton();
            button.setName("buttonNavigateNext");
            button.setAction(MorenoActionsFacade.getActionNavigateNext());
            button.setHorizontalTextPosition(SwingConstants.LEFT);
            button.setIcon(ActionsResourcesHolder.ICON_ACTION_NAVIGATE_NEXT_MED);
            getToolBar().add(button);
            buttonNavigateNext = button;
        }
        getToolBar().addSeparator(separatorDimension);
        { //buttonShowApplicationHelp
            JButton button = new JButton();
            button.setName("buttonShowApplicationHelp");
            button.setAction(MorenoActionsFacade.getActionShowAppHelp());
            button.setText(null);
            button.setIcon(ActionsResourcesHolder.ICON_ACTION_HELP_MED);
            getToolBar().add(button);
            buttonShowApplicationHelp = button;
        }
        getToolBar().add(Box.createGlue());
        { //buttonCloseReserch
            JButton button = new JButton();
            button.setName("buttonCloseReserch");
            button.setAction(MorenoActionsFacade.getActionCloseModel());
            button.setText(null);
            button.setIcon(ActionsResourcesHolder.ICON_ACTION_CLOSE_SMALL);
            button.setAlignmentY(1.0f);
            getToolBar().add(button);
            buttonCloseReserch = button;
        }
    }

    private void initStatusbar() {
        JPanel statusBar = new JPanel();
        BoxLayout boxLayout = new BoxLayout(statusBar, BoxLayout.LINE_AXIS);
        statusBar.setLayout(boxLayout);
        setStatusBar(statusBar);

        { //labelStatus
            JLabel label = new JLabel();
            label.setName("labelStatus");
            statusBar.add(label);
            Logger.getLogger("").addHandler(new Handler() {
                @Override
                public void publish(LogRecord record) {
                    if (record.getLevel().intValue() >= Level.INFO.intValue()) {
                        labelStatus.setText(record.getMessage());
                    }
                }

                @Override
                public void flush() {
                    //pass
                }

                @Override
                public void close() throws SecurityException {
                    //pass
                }

            });
            labelStatus = label;
        }
        statusBar.add(Box.createHorizontalGlue());
        { //buttonException
            JButton button = new JButton();
            button.setName("buttonException");
            button.setAction(MorenoActionsFacade.getActionDummy());
            button.setBorder(new EmptyBorder(0, 0, 0, 0));
            statusBar.add(button);
            buttonException = button;
        }
    }

    private void initLayout() {
        setWizardMode(isWizardMode());
    }

    private void initListeners() {
    }

    private void initState() {
        //setup wozard or tabs mode
        setWizardMode(isWizardMode());
    }

    //properties
    public WorkplaceNavigator getNavigator() {
        return workplace;
    }

    public boolean isWizardMode() {
        return workplace.isWizardMode();
    }

    public void setWizardMode(boolean newWizardMode) {
        boolean oldValue = isWizardMode();
        if (newWizardMode == true) {
            setComponent(workplace.getWizardWorkplace());
        } else {
            setComponent(workplace.getTabbedWorkplace());
        }
        toggleWizardMode.setSelected(isWizardMode());
        getComponent().repaint();
        firePropertyChange("wizardMode", oldValue, newWizardMode);
    }

    //actions
    //static
    public static void main(String[] args) {
        List<Field> fields = new ArrayList<Field>(Arrays.asList(MorenoMainView.class.getDeclaredFields()));
        Collections.sort(fields, new Comparator<Field>() {
            public int compare(Field o1, Field o2) {
                return -(nvl(o2.getAnnotation(Order.class)) - nvl(o1.getAnnotation(Order.class)));
            }

            int nvl(Order order) {
                if (order == null) {
                    return 0;
                } else {
                    return order.value();
                }
            }

        });
        for (Field f : fields) {
            //System.out.println(f.getName());
            if (JComponent.class.isAssignableFrom(f.getType())) {
                String shortName = f.getType().getSimpleName().toLowerCase();
                if (AbstractButton.class.isAssignableFrom(f.getType())) {
                    shortName = "button";
                }
                if (JMenu.class.isAssignableFrom(f.getType())) {
                    shortName = "menu";
                }
                if (JMenuItem.class.isAssignableFrom(f.getType())) {
                    shortName = "item";
                }
                if (JTextField.class.isAssignableFrom(f.getType())) {
                    shortName = "text";
                }

                System.out.printf(
                        "{ //%s\n" +
                        "%s %s = new %s();\n" +
                        "%s.setName(\"%s\");\n", f.getName(), f.getType().getSimpleName(), shortName, f.getType().getSimpleName(), shortName, f.getName());
                if (AbstractButton.class.isAssignableFrom(f.getType())) {
                    System.out.printf("%s.setAction(MorenoActions.get);\n", shortName);
                }
                System.out.printf("%s = %s;\n" +
                        "}\n",
                        f.getName(), shortName);
            }
        }
    }

}
